#include "MainWindow.h"

#include "CMenu.h"
#include "Central/CentralTabDragProxy.h"
#include "Managers/DataManager.h"
#include "SystemHelper.h"
#include "Tabs/DocumentTab.h"

#include <QApplication>
#include <QDesktopWidget>
#include <QMimeData>
#include <QSplitter>

QSet<MainWindow *> MainWindow::s_windows;

MainWindow::MainWindow(const QStringList &filenames, QWidget *parent) : BasicMainWindow(parent) {
    init();

    DocumentTab *tab = new DocumentTab();
    tab->setFilename(tr("File1"));

    DocumentTab *tab2 = new DocumentTab();
    tab2->setFilename(tr("File2"));

    m_tabWidget->addTab(tab);
    m_tabWidget->addTab(tab2);
}

MainWindow::MainWindow(const QList<CentralTab *> &tabs, QWidget *parent) : BasicMainWindow(parent) {
    init();
    for (auto it = tabs.begin(); it != tabs.end(); ++it) {
        m_tabWidget->addTab(*it);
    }
}

MainWindow::~MainWindow() {
    destruct();
}

void MainWindow::init() {
    s_windows.insert(this);

    setAttribute(Qt::WA_DeleteOnClose);
    setAcceptDrops(true);

    m_menuBar = new MainMenus();
    m_tabWidget = new CentralTabWidget();
    m_sidePanel = new SidePanel();

    m_splitter = new QSplitter(Qt::Horizontal);
    m_splitter->addWidget(m_sidePanel);
    m_splitter->addWidget(m_tabWidget);
    m_splitter->setStretchFactor(0, 0);
    m_splitter->setStretchFactor(1, 1);

    setMenuBar(m_menuBar);
    setCentralWidget(m_splitter);

    connect(m_tabWidget, &CentralTabWidget::titleChanged, this, &MainWindow::handleTabNameChanged);
    connect(m_tabWidget, &CentralTabWidget::tabCloseRequested, this,
            &MainWindow::handleTabCloseRequested);
    connect(m_tabWidget, &CentralTabWidget::realIndexChanged, this,
            &MainWindow::handleTabIndexChanged);
    connect(m_tabWidget, &CentralTabWidget::tabPressed, this, &MainWindow::handleTabPressed);

    m_dragProxy = new CentralTabDragProxy(this);
    m_dragProxy->setTabWidget(m_tabWidget);

    resize(1280, 720);
}

void MainWindow::destruct() {
    s_windows.remove(this);
}

MainWindow *MainWindow::primaryWindow() {
    return s_windows.isEmpty() ? nullptr : (*s_windows.begin());
}

QList<MainWindow *> MainWindow::windows() {
    return s_windows.values();
}

CentralTabWidget *MainWindow::centralTabWidget() const {
    return m_tabWidget;
}

bool MainWindow::handleTabCloseRequested(int index) {
    CentralTab *tab = tabAt(index);
    if (tab->acceptClose()) {
        closeTab(tab);
    }
    return true;
}

void MainWindow::handleTabIndexChanged(int index) {
    Q_UNUSED(index)

    CentralTab *tab = currentTab();
    if (!tab) {
        return;
    }

    reloadTitle(); // Reload Window Title refering to current tab

    //    m_scope->welcomeActions()->switchFile->setEnabled(previousTab());
}

void MainWindow::handleTabNameChanged(int index, const QString &newName) {
    Q_UNUSED(index)
    Q_UNUSED(newName)
    reloadTitle();
}

void MainWindow::handleTabPressed(int index, Qt::MouseButton button) {
    if (button == Qt::RightButton) {
        CentralTab *tab = tabAt(index);
        if (!tab) {
            return;
        }

        CMenu menu(this);

        QAction closeAction(tr("Close"), &menu);
        QAction closeOthersAction(tr("Close Others"), &menu);
        QAction closeSavedAction(tr("Close Saved"), &menu);
        QAction closeAllAction(tr("Close All"), &menu);
        QAction newWinAction(tr("Open in new window(&E)"), &menu);
        QAction revealAction(&menu);

        menu.addAction(&closeAction);
        menu.addAction(&closeOthersAction);
        menu.addAction(&closeSavedAction);
        menu.addAction(&closeAllAction);

        if (tabCount() > 1) {
            menu.addSeparator();
            menu.addAction(&newWinAction);
        }
        if ((tab->type() & CentralTab::Document) && Sys::isFileExist(tab->filename())) {
            revealAction.setText(tr("Show in %1(&S)").arg(qData->fileManagerName));
            menu.addSeparator();
            menu.addAction(&revealAction);
        } else if ((tab->type() & CentralTab::Folder) && Sys::isDirExist(tab->filename())) {
            revealAction.setText(tr("Open in %1(&S)").arg(qData->fileManagerName));
            menu.addSeparator();
            menu.addAction(&revealAction);
        }

        QAction *action = menu.exec(QCursor::pos());
        m_tabWidget->invalidateHover();

        if (action == &closeAction) {
            handleTabCloseRequested(index);
        } else if (action == &closeOthersAction) {
            for (int i = tabCount() - 1; i >= 0; --i) {
                if (i == index) {
                    continue;
                }
                if (!handleTabCloseRequested(i)) {
                    break;
                }
            }
        } else if (action == &closeSavedAction) {
            for (int i = tabCount() - 1; i >= 0; --i) {
                if (tabAt(i)->isEdited()) {
                    continue;
                }
                if (!handleTabCloseRequested(i)) {
                    break;
                }
            }
        } else if (action == &closeAllAction) {
            for (int i = tabCount() - 1; i >= 0; --i) {
                if (!handleTabCloseRequested(i)) {
                    break;
                }
            }
        } else if (action == &newWinAction) {
            CentralTab *tab = tabAt(index);
            m_tabWidget->removeTab(index);
            MainWindow *w = new MainWindow({tab});
            if (!isMaximized()) {
                w->resize(size());
            } else {
                w->resize(QApplication::desktop()->size() * 2.0 / 3.0);
            }
            w->centralize();
            w->showForward();

        } else if (action == &revealAction) {
            Sys::reveal(tabAt(index)->filename());
        }
    }
}

void MainWindow::closeTab(CentralTab *tab) {
    closeTab(m_tabWidget->indexOf(tab));
}

void MainWindow::closeTab(int index) {
    CentralTab *tab = tabAt(index);

    if (!tab || (tab->type() == CentralTab::Welcome && tabCount() == 1)) {
        return;
    }

    m_tabWidget->removeTab(index);
    tab->deleteLater(); // Cannot directly delete because menu in tab call this method

    // If all tabs are closed, then add a welcoming tab
    if (tabCount() == 0) {
        //        addWelcomeTab();
        if (tabCount() == 0) {
            close();
        }
    }
}

void MainWindow::reloadTitle() {
    setTitle(m_tabWidget->currentTitle());
}

void MainWindow::setTitle(const QString &title) {
    setWindowTitle(QString("%1 - %2").arg(title, qData->WindowTitle));
}


void MainWindow::dragEnterEvent(QDragEnterEvent *event) {
    const QMimeData *mime = event->mimeData();
    if (mime->hasUrls()) {
        event->acceptProposedAction();
    }
    if (event->isAccepted()) {
        return;
    }
    return BasicMainWindow::dragEnterEvent(event);
}

void MainWindow::dropEvent(QDropEvent *event) {
    const QMimeData *mime = event->mimeData();
    if (mime->hasUrls()) {
        auto urls = mime->urls();
        QStringList filenames;
        for (auto it = urls.begin(); it != urls.end(); ++it) {
            if (it->isLocalFile()) {
                filenames.append(Sys::removeTailSlashes(it->toLocalFile()));
            }
        }
        //        addMultipleTabs(filenames);
        event->acceptProposedAction();
    }
    if (event->isAccepted()) {
        return;
    }
    return BasicMainWindow::dropEvent(event);
}

void MainWindow::closeEvent(QCloseEvent *event) {
    bool accepted = true;
    for (int i = tabCount() - 1; i >= 0; --i) {
        if (!handleTabCloseRequested(i)) {
            accepted = false;
            break;
        }
    }
    event->setAccepted(accepted);
}
